package monitor

import (
	"bytes"
	"encoding/json"
	"fmt"
	"github.com/nick/vdamtools/apps/config"
	"github.com/nick/vdamtools/pkg/loggerv"
	"github.com/shirou/gopsutil/cpu"
	"github.com/shirou/gopsutil/v3/mem"
	"go.uber.org/zap"
	"log"
	"net/http"
	"time"
)

func GetCPUUtilizations() (float64, []float64, error) {
	// 获取每个逻辑CPU的利用率
	logicalUtilizations, err := cpu.Percent(time.Second, true)
	if err != nil {
		log.Println("Failed to get logical CPU utilizations:", err)
		return 0, nil, err
	}

	// 获取整体CPU的利用率
	overallUtilizations, err := cpu.Percent(time.Second, false)
	if err != nil {
		log.Println("Failed to get overall CPU utilization:", err)
		return 0, nil, err
	}

	// 返回整体和每个逻辑CPU的利用率
	return overallUtilizations[0], logicalUtilizations, nil
}

/*
获取内存
*/
func GetMemory() (*mem.VirtualMemoryStat, error) {
	memory, err := mem.VirtualMemory()
	if err != nil {
		log.Println("Failed to get overall CPU utilization:", err)
		return nil, err
	}
	return memory, err
}

func startMonitoring(hostname string, url string, n int) {
	ticker := time.NewTicker(time.Duration(n) * time.Second)
	defer ticker.Stop()
	for {
		select {
		case <-ticker.C:
			totalCPUUsage, coreUsages, err := GetCPUUtilizations()
			if err != nil {
				fmt.Printf("Error getting CPU utilizations: %v\n", err)
				continue
			}
			memory, err := GetMemory()
			if err != nil {
				fmt.Printf("Error getting memory: %v\n", err)
				continue
			}
			eventTime := time.Now().UnixNano() / 1000000
			data := ServerData{
				EventTime:      eventTime,
				TotalCPUUsage:  totalCPUUsage,
				CoreUsages:     coreUsages,
				MemTotal:       memory.Total,
				MemAvailable:   memory.Available,
				MemUsed:        memory.Used,
				MemFree:        memory.Free,
				MemUsedPercent: memory.UsedPercent,
				Hostname:       hostname,
			}
			err = sendServerData(url, data)
			if err != nil {
				fmt.Printf("Error sending monitoring data: %v\n", err)
			}
		}
	}
}

func sendServerData(url string, data ServerData) error {
	jsonData, err := json.Marshal(data)
	if err != nil {
		return err
	}
	loggerv.Logger.Info("send", zap.String("url", url), zap.Any("data", data))

	resp, err := http.Post(url, "application/json", bytes.NewBuffer(jsonData))
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		return fmt.Errorf("server returned non-200 status: %v", resp.Status)
	}

	return nil
}

func Run() {
	interval := config.GlobalConfig.Server.Interval
	hostname := config.GlobalConfig.Server.Hostname
	url := fmt.Sprintf("%s/apis/host", config.GlobalConfig.Dashboard.Url)
	startMonitoring(hostname, url, interval)
}
